package jmine.tec.report.impl.table.xls;

import java.math.BigDecimal;
import java.util.Locale;

import jmine.tec.report.api.table.ReportCell;
import jmine.tec.report.impl.table.RendererParameterInterface;
import jmine.tec.report.impl.table.ReportTableBuilder;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

/**
 * @author lundberg
 */
public class NumberCellXLSRenderer implements ReportCellXLSRenderer {

    protected static final String STYLE = "numberContentStyle%s";

    /**
     * {@inheritDoc}
     */
    public void render(HSSFWorkbook workbook, HSSFCell hssfCell, ReportCell cell) {
        if (cell.getValue() != null) {
            hssfCell.setCellValue(this.getDoubleValue(cell));
        }
        hssfCell.setCellStyle(this.getStyle(workbook, hssfCell, this.getDecimals(cell)));
    }

    /**
     * Retorna o número de casas decimais que deve ser utilizada na formatação
     * 
     * @param cell cell
     * @return integera
     */
    protected int getDecimals(ReportCell cell) {
        RendererParameterInterface rpi = new RendererParameterInterface(cell);
        Integer decimals = rpi.getDecimals();
        return (decimals != null) ? decimals : this.getValueScale(cell);
    }

    /**
     * Retorna o valor double da coluna.
     * 
     * @param cell cell
     * @return double
     */
    protected double getDoubleValue(ReportCell cell) {
        if (BigDecimal.class.isInstance(cell.getValue())) {
            return BigDecimal.class.cast(cell.getValue()).doubleValue();
        } else if (Number.class.isInstance(cell.getValue())) {
            return Number.class.cast(cell.getValue()).doubleValue();
        } else {
            return new BigDecimal(cell.getValue().toString()).doubleValue();
        }
    }

    /**
     * Tenta obter o valor da célula na forma de um BigDecimal
     * 
     * @param cell cell
     * @return BigDecimal
     */
    private int getValueScale(ReportCell cell) {
        if (cell.getValue() == null) {
            return 0;
        } else if (BigDecimal.class.isInstance(cell.getValue())) {
            return BigDecimal.class.cast(cell.getValue()).scale();
        } else if (Number.class.isInstance(cell.getValue())) {
            return new BigDecimal(Number.class.cast(cell.getValue()).doubleValue()).scale();
        } else {
            return new BigDecimal(cell.getValue().toString()).scale();
        }
    }

    /**
     * Obtém o estilo adequado para a célula de relatório contendo uma data.
     * 
     * @param workbook workbook
     * @param hssfCell hssfCell
     * @param decimals decimals
     * @return HSSFCellStyle
     */
    protected HSSFCellStyle getStyle(HSSFWorkbook workbook, HSSFCell hssfCell, int decimals) {
        String styleName = String.format(STYLE, decimals);
        for (short i = 0; i < workbook.getNumCellStyles(); i++) {
            HSSFCellStyle style = workbook.getCellStyleAt(i);
            if (styleName.equals(style.getUserStyleName())) {
                return style;
            }
        }
        HSSFCellStyle style = workbook.createCellStyle();
        style.cloneStyleFrom(hssfCell.getCellStyle());
        HSSFDataFormat dataFormat = workbook.createDataFormat();
        style.setDataFormat(dataFormat.getFormat(String.format(Locale.ENGLISH, "#,##%." + decimals + "f", 0.0)));
        style.setUserStyleName(styleName);
        return style;
    }

    /**
     * {@inheritDoc}
     */
    public String getRendererType() {
        return ReportTableBuilder.TYPE_NUMBER;
    }

}
